﻿using Cinch;
using FR.SAFTAnalyser.Model;
using FR.SAFTAnalyser.ViewModels.Pane;
using MEFedMVVM.Common;
using OfficeOpenXml;
using OfficeOpenXml.Table;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FR.SAFTAnalyser.ViewModels
{
    public class InvoiceViewModel : DocumentPartViewModel
    {
        public InvoiceViewModel(SourceDocumentsSalesInvoicesInvoice invoice)
            : base("Documento")
        {
            if (!Designer.IsInDesignMode)
            {
                Mediator.Instance.Register(this);

                this.CurrentInvoice = invoice;
                GetTaxResume();

                this.DoOpenExcelCommand = new SimpleCommand<object, object>(CanOpenExcel, OpenExcel);
            }
        }

        internal override void ResetSaftFile()
        {
            this.CurrentInvoice = null;
            this.CurrentInvoiceLines = null;
            this.Resumo = null;
            this.StringCertificacao = null;
        }

        SourceDocumentsSalesInvoicesInvoice currentInvoice;
        public SourceDocumentsSalesInvoicesInvoice CurrentInvoice
        {
            get { return currentInvoice; }
            set
            {
                currentInvoice = value;
                NotifyPropertyChanged(ObservableHelper.CreateArgs<InvoiceViewModel>(x => x.CurrentInvoice));

                CurrentInvoiceLines = new ObservableCollection<SourceDocumentsSalesInvoicesInvoiceLine>(currentInvoice.Line);
                if (SAFTAnalyser.SAFT.SaftAnalyser.Instance.SaftFile != null && SAFTAnalyser.SAFT.SaftAnalyser.Instance.SaftFile.MasterFiles != null && SAFTAnalyser.SAFT.SaftAnalyser.Instance.SaftFile.MasterFiles.Customer != null)
                    InvoiceCustomer = SAFTAnalyser.SAFT.SaftAnalyser.Instance.SaftFile.MasterFiles.Customer.Where(c => c.CustomerID.Equals(currentInvoice.CustomerID, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

                GetCertificationString();
            }
        }

        ObservableCollection<SourceDocumentsSalesInvoicesInvoiceLine> currentInvoiceLines;
        public ObservableCollection<SourceDocumentsSalesInvoicesInvoiceLine> CurrentInvoiceLines
        {
            get { return currentInvoiceLines; }
            set
            {
                currentInvoiceLines = value;
                NotifyPropertyChanged(ObservableHelper.CreateArgs<InvoiceViewModel>(x => x.CurrentInvoiceLines));
            }
        }

        Customer invoiceCustomer;
        public Customer InvoiceCustomer
        {
            get { return invoiceCustomer; }
            set
            {
                invoiceCustomer = value;
                NotifyPropertyChanged(ObservableHelper.CreateArgs<InvoiceViewModel>(x => x.InvoiceCustomer));
            }
        }

        ResumoIva[] resumo;
        public ResumoIva[] Resumo
        {
            get { return resumo; }
            set
            {
                resumo = value;
                NotifyPropertyChanged(ObservableHelper.CreateArgs<InvoiceViewModel>(x => x.Resumo));
            }
        }

        string stringCertificacao;
        public string StringCertificacao
        {
            get { return stringCertificacao; }
            set
            {
                stringCertificacao = value;
                NotifyPropertyChanged(ObservableHelper.CreateArgs<InvoiceViewModel>(x => x.StringCertificacao));
            }
        }

        private void GetCertificationString()
        {
            if (string.IsNullOrEmpty(this.CurrentInvoice.Hash) || this.CurrentInvoice.Hash.Length != 172)
                this.StringCertificacao = "Sem informação";
            else
                this.StringCertificacao =
                    string.Format("{0}{1}{2}{3}-Processado por Programa Certificado n.º {4}/AT"
                        , this.CurrentInvoice.Hash[0]
                        , this.CurrentInvoice.Hash[10]
                        , this.CurrentInvoice.Hash[20]
                        , this.CurrentInvoice.Hash[30]
                        , SAFTAnalyser.SAFT.SaftAnalyser.Instance.SaftFile.Header.SoftwareCertificateNumber);
        }

        private void GetTaxResume()
        {
            this.Resumo =
                (from l in this.CurrentInvoiceLines
                 group l by new { l.Tax.TaxCode, l.Tax.Item } into g
                 select new ResumoIva
                 {
                     Codigo = g.Key.TaxCode,
                     Taxa = (g.Key.Item * 0.01m).ToString("p"),
                     Valor = g.Sum(linha => linha.Item * linha.Tax.Item * 0.01m),
                     Incidencia = g.Sum(linha => linha.Item)
                 }).ToArray();
        }

        #region Commands

        public Cinch.SimpleCommand<object, object> DoOpenExcelCommand { get; set; }

        private void OpenExcel(object args)
        {
            OpenInvoiceInExcel(this.CurrentInvoice, this.CurrentInvoice.Line);
        }

        internal bool CanOpenExcel(object args)
        {
            return this.CurrentInvoiceLines != null && this.CurrentInvoiceLines.Count > 0;
        }

        #endregion

        internal static void OpenInvoiceInExcel(SourceDocumentsSalesInvoicesInvoice CurrentInvoice, SourceDocumentsSalesInvoicesInvoiceLine[] lines)
        {
            if (CurrentInvoice != null)
            {
                DataTable dtinvoice = new DataTable("Invoice");
                dtinvoice.Columns.Add("InvoiceNo", typeof(string));
                dtinvoice.Columns.Add("Estado", typeof(string));
                dtinvoice.Columns.Add("Data documento", typeof(DateTime));
                dtinvoice.Columns.Add("Data sistema", typeof(DateTime));
                dtinvoice.Columns.Add("Total s/ IVA", typeof(decimal));
                dtinvoice.Columns.Add("Total", typeof(decimal));
                dtinvoice.Columns.Add("Total imposto", typeof(decimal));
                dtinvoice.Columns.Add("Cliente", typeof(string));
                dtinvoice.Columns.Add("Periodo", typeof(int));
                dtinvoice.Columns.Add("Autofacturação", typeof(string));
                dtinvoice.Columns.Add("Transacção", typeof(string));
                dtinvoice.Columns.Add("Hash", typeof(string));
                dtinvoice.Columns.Add("Hash Test", typeof(string));
                dtinvoice.Columns.Add("Hash Control", typeof(string));

                dtinvoice.Rows.Add(
                    CurrentInvoice.InvoiceNo,
                    CurrentInvoice.DocumentStatus.InvoiceStatus.ToString(),
                    CurrentInvoice.InvoiceDate,
                    CurrentInvoice.SystemEntryDate,
                    CurrentInvoice.DocumentTotals.NetTotal,
                    CurrentInvoice.DocumentTotals.GrossTotal,
                    CurrentInvoice.DocumentTotals.TaxPayable,
                    CurrentInvoice.CustomerID,
                    Int32.Parse(CurrentInvoice.Period),
                    CurrentInvoice.SpecialRegimes.SelfBillingIndicator,
                    CurrentInvoice.TransactionID,
                    CurrentInvoice.Hash,
                    CurrentInvoice.HashTest,
                    CurrentInvoice.HashControl);

                ExcelPackage pck = new ExcelPackage();
                var wsEnum = pck.Workbook.Worksheets.Add("SAFT Invoice");
                wsEnum.Cells["C2"].Style.Numberformat.Format = "yyyy-MM-dd";
                wsEnum.Cells["D2"].Style.Numberformat.Format = "yyyy-MM-dd hh:mm:ss";

                wsEnum.Cells["E2"].Style.Numberformat.Format = @"#,##0.00";
                wsEnum.Cells["F2"].Style.Numberformat.Format = @"#,##0.00";
                wsEnum.Cells["G2"].Style.Numberformat.Format = @"#,##0.00";
                //Load the collection starting from cell A1...
                wsEnum.Cells["A1"].LoadFromDataTable(dtinvoice, true, TableStyles.Medium9);
                wsEnum.Cells[wsEnum.Dimension.Address].AutoFitColumns();

                if (lines != null)
                {
                    DataTable dtlines = new DataTable("InvoiceLines");

                    dtlines.Columns.Add("Nº linha", typeof(int));
                    dtlines.Columns.Add("Código produto", typeof(string));
                    dtlines.Columns.Add("Descrição produto", typeof(string));
                    dtlines.Columns.Add("Quantidade", typeof(decimal));
                    dtlines.Columns.Add("Preço unitário", typeof(decimal));
                    dtlines.Columns.Add("Valor", typeof(decimal));
                    dtlines.Columns.Add("Desconto", typeof(decimal));
                    dtlines.Columns.Add("Tipo operação", typeof(string));
                    dtlines.Columns.Add("Imposto", typeof(decimal));
                    dtlines.Columns.Add("Isenção imposto", typeof(string));
                    dtlines.Columns.Add("Unidade medida", typeof(string));
                    dtlines.Columns.Add("Data", typeof(DateTime));
                    dtlines.Columns.Add("Descrição", typeof(string));
                    dtlines.Columns.Add("DocNumber", typeof(string));

                    foreach (var line in lines)
                    {
                        dtlines.Rows.Add(
                            line.LineNumber,
                            line.ProductCode,
                            line.ProductDescription,
                            line.Quantity,
                            line.UnitPrice,
                            line.Item,
                            line.SettlementAmount,
                            line.ItemElementName.ToString(),
                            line.Tax.Item,
                            line.TaxExemptionReason,
                            line.UnitOfMeasure,
                            line.TaxPointDate,
                            line.Description,
                            line.InvoiceNo);
                    }

                    var wsEnumLines = pck.Workbook.Worksheets.Add("SAFT Invoice Lines");
                    wsEnumLines.Cells[string.Format("L2:L{0}", lines.Length + 1)].Style.Numberformat.Format = "yyyy-MM-dd hh:mm:ss";

                    wsEnumLines.Cells[string.Format("D2:D{0}", lines.Length + 1)].Style.Numberformat.Format = @"#,##0.00";
                    wsEnumLines.Cells[string.Format("E2:E{0}", lines.Length + 1)].Style.Numberformat.Format = @"#,##0.00";
                    wsEnumLines.Cells[string.Format("F2:F{0}", lines.Length + 1)].Style.Numberformat.Format = @"#,##0.00";
                    wsEnumLines.Cells[string.Format("G2:G{0}", lines.Length + 1)].Style.Numberformat.Format = @"#,##0.00";

                    wsEnumLines.Cells[string.Format("D{0}", lines.Length + 2)].Formula = string.Format("SUM(D2:D{0})", lines.Length + 1);
                    wsEnumLines.Cells[string.Format("E{0}", lines.Length + 2)].Formula = string.Format("SUM(E2:E{0})", lines.Length + 1);
                    wsEnumLines.Cells[string.Format("F{0}", lines.Length + 2)].Formula = string.Format("SUM(F2:F{0})", lines.Length + 1);
                    wsEnumLines.Cells[string.Format("G{0}", lines.Length + 2)].Formula = string.Format("SUM(G2:G{0})", lines.Length + 1);

                    //Load the collection starting from cell A1...
                    wsEnumLines.Cells["A1"].LoadFromDataTable(dtlines, true, TableStyles.Medium9);
                    wsEnumLines.Cells[wsEnum.Dimension.Address].AutoFitColumns();
                }

                //...and save
                var fi = new FileInfo(Path.GetTempPath() + Path.GetRandomFileName() + ".xlsx");

                pck.SaveAs(fi);

                Process.Start(fi.FullName);
            }
        }
    }
}
